﻿using Freebase4net.Operators;
using System;
using System.Reflection;

namespace Freebase4net
{
    public static class TypeSwitch
    {
        public class CaseInfo
        {
            public bool IsDefault { get; set; }
            public Type Target { get; set; }
            public Action<object> Action { get; set; }
        }

        public static void Do(PropertyInfo source, params CaseInfo[] cases)
        {
            var type = source.PropertyType;
            foreach (var entry in cases)
            {
                if (entry.IsDefault || 
                    type == entry.Target ||
                    (type.IsInstanceOfType(entry.Target) && entry.Target != typeof(object)))
                {
                    entry.Action(source);
                    break;
                }
            }
        }

        public static void Do(Object source, params CaseInfo[] cases)
        {
            var type = source.GetType();
            foreach (var entry in cases)
            {
                if (entry.IsDefault || 
                    type == entry.Target ||
                    (entry.Target.IsAssignableFrom(type) && entry.Target != typeof(object)) 
                )
                {
                    entry.Action(source);
                    break;
                }
            }
        }

        public static CaseInfo Case<T>(Action action)
        {
            return new CaseInfo()
            {
                Action = x => action(),
                Target = typeof(T)
            };
        }

        public static CaseInfo Case<T>(Action<T> action)
        {
            return new CaseInfo()
            {
                Action = (x) => action((T)x),
                Target = typeof(T)
            };
        }

        public static CaseInfo Default(Action action)
        {
            return new CaseInfo()
            {
                Action = x => action(),
                IsDefault = true
            };
        }
    }
}
